/**
 * Created with IntelliJ IDEA.
 * User: zzl
 * Date: 12-12-6
 * To change this template use File | Settings | File Templates.
 */
(function ($, undefined) {

    var Menu = function (ul, options) {
        this.$ul = $(ul);
        this.options = options;
        this.setup();
    };

    var proto = { constructor: Menu };
    Menu.prototype = proto;

    proto.setup = function () {
        var me = this;

        me.$ul.addClass('menu');

        me.$ul.find('li').each(function () {
            var $li = $(this);
            if (jsex.trim($li.text()) == '-') {
                $li.html('<span></span>').addClass('separator');
            }
            //
            if ($li.has('>ul').length) {
                me.setupParentMenuItem($li);
            }
            else {
//                me.setupLeafMenuItem($li);
            }
            //

        });

        me.$ul.on('mouseover', 'li', function (e) {
            me.li_mouseOver($(this), e);
        });
        me.$ul.on('mouseout', 'li', function(e) {
            me.li_mouseOut($(this), e);
        });
        $(document).on('mousedown.menu', function(e) {
            if($.contains(me.$ul[0], e.target)) {
                return;
            }
            me.$activeMenu = null;
            me.hideSubMenu();
        });
    };

    proto.hideSubMenuNow = function () {
        var me = this;
        if (me.hideSubMenuFuture) {
            clearTimeout(me.hideSubMenuFuture.timer);
            me.hideSubMenu();
            me.hideSubMenuFuture = null;
        }
    };

    proto.cancelShowSubMenu = function () {
        var me = this;
        if (me.showSubMenuFuture) {
            clearTimeout(me.showSubMenuFuture.timer);
            me.showSubMenuFuture = null;
        }
    };

    proto.li_mouseOver = function ($li, e) {
        var me = this;
        if ($li.hasClass('subMenuShown')) {
            return;
        }

        me.cancelShowSubMenu();
        me.$activeMenu = $li.parent();

        if (me.$lastActiveSubMenu != null && !me.$lastActiveSubMenu.is(me.$activeMenu)) {
            me.createHideSubMenuFuture();
        }

        if ($li.hasClass('hasSubMenu')) {
            var timer = setTimeout(function () {
                me.hideSubMenuNow();
                me.showSubMenu($li);
            }, me.options.showDelay);
            me.showSubMenuFuture = {
                timer: timer,
                $li: $li
            }
        }

    };

    proto.li_mouseOut = function ($li, e) {
        var me = this;
        if(me.showSubMenuFuture && me.showSubMenuFuture.$li.is($li)) {
            me.cancelShowSubMenu();
        }
    };

    proto.setupParentMenuItem = function ($li) {
        var me = this;
        var $ul = $li.children('ul');
        $ul.hide();
        $ul.addClass('menu sub');
        $li.addClass('hasSubMenu');
        $('<div class="arrow"></div>').appendTo($li);
    };

    proto.showSubMenu = function ($li) {
        var me = this;
        me.showSubMenuFuture = null;
        if ($li.hasClass('subMenuShown')) {
            return;
        }
        $li.addClass('subMenuShown');
        var $ul = $li.find('>ul');
        var pos = {
            left: $li.outerWidth() - 5,
            top: -3
        };
        var css = {
            left: pos.left + 'px',
            top: pos.top + 'px'
        };
        $ul.css(css).show();
        me.$lastActiveSubMenu = $ul;
    };

    proto.createHideSubMenuFuture = function () {
        var me = this;
        //
        var $menu = me.$lastActiveSubMenu;
        while ($menu && $menu.length && !$menu.is(me.$activeMenu)) {
            var $parentLi = $menu.parent();
            $parentLi.removeClass('subMenuShown');
            $menu = $parentLi.parent();
        }


        //
        var timer = setTimeout(function () {
            me.hideSubMenu();
        }, me.options.hideDelay);
        me.hideSubMenuFuture = {
            timer: timer
        };
    };

    proto.hideSubMenu = function () {
//        console.log('hideSubMenu@' + new Date());
        var me = this;
        me.hideSubMenuFuture = null;

        var $menu = me.$lastActiveSubMenu;
        while ($menu && $menu.length &&
            !$menu.is(me.$activeMenu) &&
            !$menu.is(me.$ul)) {

            var $parentLi = $menu.parent();
            $parentLi.removeClass('subMenuShown');
            $menu.hide();
            $menu = $parentLi.parent();
        }
        me.$lastActiveSubMenu = me.$ul.is(me.$activeMenu)? null: me.$activeMenu;
    };

    $.fn.menu = $.addPluginFn('menu', Menu, {
        showDelay: 500,
        hideDelay: 500
    });

})(jQuery);